﻿//Copyright 2008 Jordan Knight
//This code is licenced under Creative Commons Licence: http://creativecommons.org/licenses/by-sa/3.0/

using System;
using System.Windows;
using System.Windows.Media.Animation;
using System.Collections.Generic;
using System.Windows.Threading;

namespace XamlingCore.SL.AnimationChainer
{
    public class AnimationChainManager
    {

        static int storyBoardCount = 0;

        private object lockObj = new object();

        List<AnimationGroup> animationGroups = new List<AnimationGroup>();

        FrameworkElement ele;

        bool isRunning;

        string guid;

        Storyboard sb = null;

        public AnimationChainManager(FrameworkElement ele)
        {
            this.ele = ele;
            storyBoardCount++;
            guid = "Storyboard_" + storyBoardCount.ToString();
        }

        /// <summary>
        /// Wait until currently executing animations end before invoking this animation group
        /// </summary>
        /// <param name="group"></param>
        
        #region "Fluent"

        public AnimationGroup Add()
        {       
            AnimationGroup ag = new AnimationGroup();
            animationGroups.Add(ag);
            return ag;
        }       

        #endregion

        public void Stop()
        {
            if (sb != null)
            {
                sb.Stop();
                ele.Resources.Remove(guid);
            }
        }

        public void Pause()
        {
            if (sb != null)
            {
                sb.Pause();
            }
        }
        public void Resume()
        {
            if (sb != null)
            {
                sb.Resume();
            }
        }

        public void Begin(TimeSpan delay)
        {
            if (delay != TimeSpan.Zero)
            {
                DispatcherTimer t = new DispatcherTimer();
                t.Tick += (s, e) =>
                {
                    t.Stop();
                    start();
                };
                t.Interval = delay;
                t.Start();
            }
            else
            {
                start();
            }
                   
        }
        void start()
        {
            if (sb != null)
            {
                sb.Stop();        
                ele.Resources.Remove(guid);                        
            }

            storyBoardCount++;

            sb = new Storyboard();            
            
            ele.Resources.Add(guid,  sb);

            sb.Completed += (s, e) =>
            {
                ele.Resources.Remove(guid);
            };

            foreach (AnimationGroup g in animationGroups)
            {
                g.Start(sb);
            }

            //animationGroups.Clear();
            
            sb.Dispatcher.BeginInvoke(() =>
            {
                sb.Begin();
            });
        }      

      

        //void begin()
        //{

           

        //    //if (waiting.Count > 0 && animationGroups.Count == 0)
        //    //{
        //    //    beginWaiting();
        //    //}
        //    //else
        //    //{
        //    //    if (serialMode)
        //    //    {
        //    //        serialAnims();
        //    //    }
        //    //    else
        //    //    {
        //           // asyncAnims();
        //    //    }
        //    //}
        //}

        //private void asyncAnims()
        //{
        //    if (Monitor.TryEnter(lockObj, 20000))
        //    {
        //        try
        //        {
        //            TimeSpan? currentOffset = GroupDelay;
        //            foreach (AnimationGroup g in animationGroups)
        //            {
        //                g.Complete += new EventHandler(g_Complete);
        //                g.Start(currentOffset);
        //                if (currentOffset.HasValue)
        //                {
        //                    currentOffset += GroupDelay.Value;
        //                }
        //            }
        //            animationGroups.Clear();
        //        }
        //        finally
        //        {
        //            Monitor.Exit(lockObj);
        //        }
        //    }
        //}

        //void g_Complete(object sender, EventArgs e)
        //{
        //    if (Monitor.TryEnter(lockObj, 20000))
        //    {
        //        try
        //        {
        //            AnimationGroup g = sender as AnimationGroup;
        //            animationGroups.Remove(g);

        //            if (animationGroups.Count == 0)
        //            {
        //                beginWaiting();
        //            }
        //        }
        //        finally
        //        {
        //            Monitor.Exit(lockObj);
        //        }
        //    }
        //}

        //private void serialAnims()
        //{
           
        //            if (animationGroups.Count > 0)
        //            {
        //                AnimationGroup ag = animationGroups[0];
        //                ag.Complete += new EventHandler(ag_Complete);
        //                animationGroups.RemoveAt(0);
        //                ag.Start(null);
        //            }
        //        }
        //        finally
        //        {
        //            Monitor.Exit(lockObj);
        //        }
        //    }
        //}

        //void beginWaiting()
        //{
        //    if (Monitor.TryEnter(lockObj, 20000))
        //    {
        //        try
        //        {
        //            if (waiting.Count > 0 && animationGroups.Count == 0)
        //            {
        //                waiting.ForEach(p => animationGroups.Add(p));
        //                waiting.Clear();
        //                begin();
        //            }
        //        }
        //        finally
        //        {
        //            Monitor.Exit(lockObj);
        //        }

        //    }
        //}

        //void ag_Complete(object sender, EventArgs e)
        //{
        //    AnimationGroup ag = sender as AnimationGroup;
        //    ag.Complete -= new EventHandler(ag_Complete);

        //    if (animationGroups.Count == 0)
        //    {
        //        beginWaiting();
        //    }
        //    else
        //    {
        //        begin();
        //    }

        //}

        //TimeSpan? groupDelay = null;
        //public TimeSpan? GroupDelay
        //{
        //    get
        //    {
        //        return groupDelay;
        //    }
        //    set
        //    {
        //        groupDelay = value;
        //    }
        //}

    }
}
